package com.ktdaddy.service.impl;

import com.ktdaddy.enums.WhaleErrorCode;
import com.ktdaddy.exception.BusinessRuntimeException;
import com.ktdaddy.manager.PermissionManager;
import com.ktdaddy.pojo.Permission;
import com.ktdaddy.request.CreatePermissionReq;
import com.ktdaddy.request.UpdatePermissionReq;
import com.ktdaddy.vo.PermVO;
import com.ktdaddy.mapper.PermissionMapper;
import com.ktdaddy.mapper.RolePermissionRelMapper;
import com.ktdaddy.pojo.RolePermissionRel;
import com.ktdaddy.service.PermService;
import com.ktdaddy.service.RoleService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author kdaddy@163.com
 * @date 2021/4/27 22:54
 */
@Service
public class PermServiceImpl implements PermService {

    @Autowired
    private RoleService roleService;

    @Resource
    private RolePermissionRelMapper rolePermissionRelMapper;

    @Resource
    private PermissionMapper permissionMapper;

    @Resource
    private PermissionManager permissionManager;

    /**
     * 根据用户名找到相关的权限信息
     * @param kernelName
     * @return
     */
    @Override
    public Set<String> loadByKernelName(String kernelName) {
        Set<String> roleCodes = roleService.loadByKernelName(kernelName);

        Set<String> permCodes = new HashSet<>();

        Example example = new Example(RolePermissionRel.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("roleCode",roleCodes);

        List<RolePermissionRel> rolePermissions = rolePermissionRelMapper.selectByExample(example);
        if(rolePermissions.isEmpty()){
            return permCodes;
        }

        permCodes = rolePermissions.stream().map(RolePermissionRel::getPermissionCode).collect(Collectors.toSet());
        return permCodes;
    }

    private boolean isRootNode(String permissionName){
        if(StringUtils.isEmpty(permissionName)){
            return false;
        }
        //判断menuName是否是根节点
        Example example = new Example(Permission.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("permissionName",permissionName);
        criteria.andEqualTo("parentId",0);
        Permission permission = permissionMapper.selectOneByExample(example);
        return !Objects.isNull(permission);
    }

    /**
     * 根据子节点名称查询父节点
     * @param childPermName
     * @return
     */
    private Permission queryParentByChildName(String childPermName){
        Permission permission = this.queryPermissionByName(childPermName);

        if(Objects.isNull(permission)){
           return null;
        }

       return permissionMapper.selectByPrimaryKey(permission.getParentId());
    }

    private Permission queryPermissionByName(String name){
        Example example = new Example(Permission.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("permissionName",name);
        Permission permission = permissionMapper.selectOneByExample(example);
        return permission;
    }


    @Override
    public List<PermVO> getPermList(String menuName, Integer status) {
        List<PermVO> result = new ArrayList<>();
        String rootName = null;
        String childName = null;

        if(isRootNode(menuName)){
            rootName = menuName;
        }else {
            childName = menuName;
            //如果childName不为空，则查询其父节点名称
            if(!StringUtils.isEmpty(childName)){
                Permission parentPermission = queryParentByChildName(childName);
                if(Objects.isNull(parentPermission)){
                    return result;
                }
                rootName = parentPermission.getPermissionName();
            }
        }

        List<PermVO> rootPermBOList = permissionMapper.queryRootByTitleAndStatus(rootName,status);

        if(!StringUtils.isEmpty(rootName) && rootPermBOList.isEmpty()){
            //判断是否根节点，如果为非根节点，则返回当前树
            rootPermBOList = permissionMapper.queryParentByTitleAndStatus(rootName,status);

        }

        if(CollectionUtils.isEmpty(rootPermBOList)){
            return result;
        }

        for(PermVO permVO : rootPermBOList){
            fetchAndBuildChildren(permVO,childName,status);
            result.add(permVO);
        }
        return rootPermBOList;
    }

    @Override
    public boolean createPermission(CreatePermissionReq createPermissionReq) {
        // 校验当前菜单是否已经存在
        createPermissionParamCheck(createPermissionReq);
        // 创建当前菜单
        permissionManager.savePermission(createPermissionReq);
        return true;
    }

    @Override
    public boolean updatePermission(UpdatePermissionReq updatePermissionReq) {
        // 更新当前权限菜单
        permissionManager.updatePermission(updatePermissionReq);
        return true;
    }

    @Override
    public boolean isPermissionExit(String permissionName) {
        Permission permission = permissionManager.findByPermissionName(permissionName);
        return !Objects.isNull(permission);
    }

    @Override
    public void deletePermission(Integer permissionId) {
        permissionManager.deletePermission(permissionId);
    }


    private void createPermissionParamCheck(CreatePermissionReq createPermissionReq) {
        //根据menuName以及Type判断当前的菜单是否已经存在
        Permission permission = permissionManager.findByMenuNameAndType(createPermissionReq.getMenuName(),createPermissionReq.getType());
        if(!Objects.isNull(permission)){
            throw new BusinessRuntimeException(WhaleErrorCode.MENU_EXIST_ERROR);
        }
    }

    /**
     * 构建并获取子节点
     * @param permVO
     */
    private void fetchAndBuildChildren(PermVO permVO,String title,Integer status) {
        List<PermVO> children = permissionMapper.queryChildByTitleAndStatus(permVO.getId(),title,status);
        if(!children.isEmpty()){
            for(PermVO childPermVO : children){
                fetchAndBuildChildren(childPermVO,title,status);
            }
            permVO.setChildren(children);
        }
    }
}
